#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>

// //volatile: 保持内存可见性!
// volatile int quit = 0;
 
void Count(int cnt)
{
    while(cnt)
    {
        printf("cnt: %2d\r", cnt);
        fflush(stdout);
        cnt--;
        sleep(1);
    }
    printf("\n");
}

void handler(int signo)
{

    //1. 我有非常多的子进程，在同一时刻退出了
    

    //waitpid(-1) -> while(1)
    //2.我有非常多的子进程，在同一时刻只有一部分退出了
    while(1)
    {
        pid_t ret = waitpid(-1, NULL, WNOHANG);
        if(ret == 0) break;
    }

    printf("pid: %d, %d号信号，正在被捕捉！\n", getpid(), signo);
    // printf("quit: %d", quit);
    // quit = 1;
    // printf("-> %d\n", quit);
}


int main()
{
    //显示的设置对SIGCHLD进行忽略
    signal(SIGCHLD, SIG_IGN);
    signal(SIGCHLD, SIG_DFL);

    printf("我是父进程，%d, ppid: %d\n", getpid(), getppid());

    pid_t id = fork();
    if(id == 0)
    {
        printf("我是子进程，%d, ppid: %d, 我要退出啦\n", getpid(), getppid());
        Count(5);
        exit(1);
    }

    while(1) 
        sleep(1);

    return 0;
}


// int main()
// {
//     signal(2, handler);
//     while(!quit);
//     printf("注意，我是正常退出的！\n");
//     return 0;
// }



// int main()
// {
//     signal(SIGCHLD, handler);
//     pid_t id = fork();
//     if(id == 0)
//     {
//         printf("我是子进程，%d, ppid: %d, 我要退出啦\n", getpid(), getppid());
//         Count(5);
//         exit(1); 
//     }
//     while(1) Count(1);
// }






// #include<iostream>
// #include<unistd.h>
// #include<cstdio>
// #include<signal.h>

// using namespace std;
// void Count(int cnt)
// {
//     while(cnt)
//     {
//         printf("cnt: %2d\r", cnt);
//         fflush(stdout);
//         cnt--;
//         sleep(1);
//     }
//     printf("\n");
// }

// void handler(int signo)
// {
//     cout << "get a signo: " << signo << "正在处理中... " << endl;
//     Count(120);
// }

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_handler = handler;
//     act.sa_flags = 0;
//     sigemptyset(&act.sa_mask);
//     for(int i=3; i<=31; i++)
//         sigaddset(&act.sa_mask, i);

//     sigaction(SIGINT, &act, &oact);
//     while(true)
//     {
//         sleep(1);
//     }

//     return 0;
// }

//1. 当我们进行正在抵达某一个信号期间，同类型信号无法被抵达！ -- 当当前信号正在被捕捉，系统会
//   自动将当前性加入到进程的信号屏蔽字，block；当信号完成捕捉，系统又会自动解除对该信号的屏蔽
//  （一般一个信号被解除屏蔽的时候，会自动进行抵达当前屏蔽字信号，如果该信号已经被pending的话，没有就不做任何动作！
//  --因此，我们进程处理信号的原则是串行的处理同类型的信号，不允许递归。